Building Our Way to Affordability: A YIMBY Policy Analysis

Author

Shreya Karki

Published

December 13, 2025

1 Introduction

Housing affordability is one of America’s most pressing urban challenges. This analysis identifies the nation’s most pro-housing metropolitan areas by examining construction patterns, economic opportunity, and housing costs across Core-Based Statistical Areas.

Following the YIMBY idea that permissive zoning and increased housing supply can reduce costs and support more dynamic, inclusive communities, we assess which regions are building enough homes to meet demand and which are falling behind.

2 Data Relationship Diagram

TipKey Data Relationships
  • All ACS tables (INCOME, RENT, POPULATION, HOUSEHOLDS) share the composite key GEOID + year.
  • PERMITS uses CBSA, which corresponds to ACS GEOID, joins on geography + year.
  • WAGES uses BLS industry codes (e.g., 101, 1011) that approximate but do not exactly match NAICS in INDUSTRY_CODES; this link is conceptual.
  • WAGES connects to ACS and PERMITS after transforming CBSA → “C” + first 4 digits (e.g., 10180 → C1018).
  • For clarity, not every possible line is drawn — the diagram shows only the primary joins used in analysis.

This ERD was created in dbdiagram.io and embedded as an SVG for best visual clarity.

3 Construction Leadership & Housing Supply Analysis (Data Exploration)

3.1 National Housing Production Leaders: 2010-2019

Code
# Identify metropolitan areas with highest housing production
top_housing_metros <- inner_join(PERMITS, INCOME, join_by(CBSA == GEOID), 
           suffix = c("_permits", "_income")) |>
  filter(year_permits >= 2010, year_permits <= 2019) |>
  group_by(NAME) |>
  summarise(total_units = sum(new_housing_units_permitted, na.rm = TRUE)) |>
  arrange(desc(total_units)) |>
  slice_max(total_units, n = 1) |>
  ungroup()

The Dallas-Fort Worth-Arlington, TX Metro Area metropolitan area permitted 6,451,564 new housing units from 2010-2019, demonstrating the scale achievable under pro-housing policies. This level of production represents a benchmark for regional housing growth targets.

3.2 Market Volatility Analysis: Albuquerque Case Study

Table: Annual Housing Production — Albuquerque Metro Area
Code
library(DT)

# Analyze construction patterns in a mid-sized metro
albuquerque_construction <- PERMITS |>
  filter(CBSA == 10740) |>
  group_by(year) |>
  summarise(`Housing Units Permitted` = sum(new_housing_units_permitted, na.rm = TRUE)) |>
  arrange(year)

datatable(
  albuquerque_construction,
  caption = 'Annual Housing Production: Albuquerque Metropolitan Area',
  options = list(pageLength = 10, searching = FALSE)
)

Albuquerque’s housing permits peaked in 2021, with the highest pre-pandemic level recorded in 2013.

Interpretation: This pattern shows a brief spike rather than a steady climb. To judge local homebuilding capacity, it is better to look at multi-year trajectories than any single high point.

3.3 Regional Income Distribution Patterns

Code
# filter year 
income_2015 <- INCOME |> 
  filter(year == 2015)

# inner-join tables and create a new column 
income_2015 <- income_2015 |>
  inner_join(HOUSEHOLDS, by = c("GEOID", "year")) |>
  inner_join(POPULATION, by = c("GEOID", "year")) |>
  select(GEOID, NAME, year, household_income, households, population) |>
  mutate(total_income_cbsa = household_income * households,
         state = str_extract(NAME, ", (.{2})", group = 1))

# state with highest average individual income
top_state_income <- income_2015 |>
  group_by(state) |>
  summarise(total_income_state = sum(total_income_cbsa, na.rm = TRUE),
            total_population_state = sum(population, na.rm = TRUE)) |>
  mutate(avg_individual_income = total_income_state / total_population_state) |>
  arrange(desc(avg_individual_income)) |>
  slice_max(avg_individual_income, n = 1)

In DC, the average individual income was the highest in 2015 at approximately $33,233 per person.

Interpretation: High income alone does not ensure affordability. Without enough housing, rents rise faster than wages.

3.4 High-Skill Employment Distribution

Code
# Filter WAGES for data scientists (NAICS 5182)
Data_scientist <- WAGES |>
  filter(INDUSTRY == 5182) |>
  select(YEAR, FIPS, EMPLOYMENT, AVG_WAGE) |>
  mutate(std_cbsa = paste0(FIPS, "0"))

# Prepare POPULATION table for joining (to get CBSA names)
POP_join <- POPULATION |>
  mutate(std_cbsa = paste0("C", GEOID)) |>
  select(std_cbsa, NAME, year)

# Join to find which CBSA had the most data scientists each year
ds_named <- Data_scientist |>
  inner_join(POP_join, by = join_by(std_cbsa, YEAR == year)) |>
  group_by(YEAR, NAME) |>
  summarise(EMPLOYMENT = sum(EMPLOYMENT, na.rm = TRUE)) |>
  slice_max(EMPLOYMENT, n = 1) |>
  arrange(YEAR)

In the latest year (2023), San Francisco-Oakland-Fremont, CA Metro Area has the most data scientists. New York–Newark–Jersey City last held the top spot in 2015.

Interpretation: Fast growth in high-paying tech jobs raises housing demand. Cities that permit new homes steadily can prevent rent spikes as their job markets expand.

3.5 Financial Sector Concentration: NYC Case Study

Code
# Filter NYC CBSA (find name containing "New York")
NYC_wages <- WAGES |>
  mutate(std_cbsa = paste0(FIPS, "0")) |>
  inner_join(POPULATION |> 
               mutate(std_cbsa = paste0("C", GEOID)) |> 
               select(std_cbsa, NAME),
             by = "std_cbsa") |>
  filter(str_detect(NAME, "New York"))

# Total wages in NYC by year
nyc_total <- NYC_wages |>
  group_by(YEAR) |>
  summarise(total_wages = sum(TOTAL_WAGES, na.rm = TRUE))

# Finance & Insurance wages (NAICS 52) in NYC by year
nyc_fin <- NYC_wages |>
  filter(INDUSTRY == 52) |>
  group_by(YEAR) |>
  summarise(finance_wages = sum(TOTAL_WAGES, na.rm = TRUE))

# Combine and calculate the fraction
nyc_share <- left_join(nyc_total, nyc_fin, by = "YEAR") |>
  mutate(finance_share = finance_wages / total_wages)

# year when the share peaked
nyc_share |>
  slice_max(finance_share, n = 1)
# A tibble: 1 × 4
   YEAR total_wages finance_wages finance_share
  <dbl>       <dbl>         <dbl>         <dbl>
1  2014     3.62e13 1667478619954        0.0460
Code
nyc_share_peak <- nyc_share |> slice_max(finance_share, n = 1)

In the New York City CBSA, workers employed in the Finance and Insurance industries (NAICS 52) earned about 4.6% of all wages.

This share peaked in 2014, showing how important finance remains to NYC’s economy.

Interpretation: Finance jobs bring high wages, but without new housing construction, those wage gains mostly raise rents instead of improving overall affordability.

5 Rent Burden: Understanding Housing Affordability

5.0.1 Defining the Metric

Rent burden measures the share of household income spent on rent — a direct indicator of housing affordability.
The INCOME and RENT tables are joined by geography and year to compute:

Rent Burden % = (Monthly Rent × 12) / Household Income × 100

To make comparisons meaningful across regions and years, the metric is standardized so that 0 = lowest and 100 = highest rent burden observed in the study period.

Code
# Standardize rent burden metric
rent_burden_data <- INCOME |>
  inner_join(RENT, by = c("GEOID", "year")) |>
  select(-NAME.y) |>
  rename(City_Name = NAME.x) |>
  mutate(
    yearly_rent = monthly_rent * 12,
    rent_income_ratio = yearly_rent / household_income,
    rent_burden_percent = rent_income_ratio * 100
  )

lowest_burden <- min(rent_burden_data$rent_burden_percent, na.rm = TRUE)
highest_burden <- max(rent_burden_data$rent_burden_percent, na.rm = TRUE)

rent_burden_data <- rent_burden_data |>
  mutate(
    burden_score = 100 * (rent_burden_percent - lowest_burden) /
                     (highest_burden - lowest_burden)
  )

5.2 Priority Intervention Regions

Table: Highest Rent Burden
Code
latest_year <- max(rent_burden_data$year, na.rm = TRUE)

most_burdened <- rent_burden_data |>
  filter(year == latest_year) |>
  select(
    City = City_Name,
    Year = year,
    `Monthly Rent` = monthly_rent,
    `Household Income` = household_income,
    `Rent Burden %` = rent_burden_percent,
    `Burden Score` = burden_score
  ) |>
  mutate(
    `Monthly Rent` = round(`Monthly Rent`, 0),
    `Household Income` = round(`Household Income`, 0),
    `Rent Burden %` = round(`Rent Burden %`, 1),
    `Burden Score` = round(`Burden Score`, 1)
  ) |>
  arrange(desc(`Burden Score`)) |>
  head(5)

datatable(
  most_burdened,
  caption = paste("Cities with Highest Rent Burden -", latest_year),
  options = list(searching = FALSE)
)
Code
# Calculate values for policy insight
top_city <- most_burdened$City[1]
top_burden <- most_burdened$`Rent Burden %`[1]
top_score <- most_burdened$`Burden Score`[1]

Interpretation: Clearlake, CA Micro Area faces the highest rent burden in the latest year, with residents spending about 31.2% of income on rent (standardized score 72.9).

This indicates acute affordability pressure, consistent with demand outpacing new supply. These metros are strong candidates for targeted permitting reforms and federal YIMBY incentives to expand rental stock quickly.

5.3 Affordable Housing Models

Table: Lowest Rent Burden
Code
least_burdened <- rent_burden_data |>
  filter(year == latest_year) |>
  select(
    City = City_Name,
    Year = year,
    `Monthly Rent` = monthly_rent,
    `Household Income` = household_income,
    `Rent Burden %` = rent_burden_percent,
    `Burden Score` = burden_score
  ) |>
  mutate(
    `Monthly Rent` = round(`Monthly Rent`, 0),
    `Household Income` = round(`Household Income`, 0),
    `Rent Burden %` = round(`Rent Burden %`, 1),
    `Burden Score` = round(`Burden Score`, 1)
  ) |>
  arrange(`Burden Score`) |>
  head(5)

datatable(
  least_burdened,
  caption = paste("Cities with Lowest Rent Burden -", latest_year),
  options = list(searching = FALSE)
)
Code
# Calculate values for policy insight
bottom_city <- least_burdened$City[1]
bottom_burden <- least_burdened$`Rent Burden %`[1]
bottom_score <- least_burdened$`Burden Score`[1]

Interpretation: Laconia, NH Micro Area indicates the lowest rent burden in the latest year, with residents spending about 12.7% of income on rent and a standardized score of 1.6.

This outcome is consistent with ample new supply and/or strong income growth, suggesting that steady permitting and streamlined approvals can keep housing costs in check.

6 Housing Growth: Measuring Supply Responsiveness

Housing growth captures how effectively cities add homes to match demand.

Using permit and population data, two complementary indicators were developed:
- an instantaneous production metric, measuring new housing relative to population size; and
- a rate-based growth metric, comparing permitting to five-year population change.

Combining these yields a composite housing growth score, which highlights metros that are both building actively and scaling with demographic trends.

Code
# Calculate housing growth metrics using population and permits data
library(dplyr)

housing_growth_data <- POPULATION |>
  inner_join(PERMITS, by = c("GEOID" = "CBSA", "year")) |>
  arrange(NAME, year) |>
  group_by(NAME) |>
  mutate(
    pop_5yr_growth = (population - lag(population, 5)) / lag(population, 5) * 100,
    permits_per_1000 = (new_housing_units_permitted / population) * 1000,
    permits_vs_growth = ifelse(pop_5yr_growth > 0, 
                              new_housing_units_permitted / (population * pop_5yr_growth / 100), 
                              NA)
  ) |>
  ungroup() |>
  filter(year >= 2014)

housing_growth_data <- housing_growth_data |>
  mutate(
    instant_score = 100 * (permits_per_1000 - min(permits_per_1000, na.rm = TRUE)) / 
                   (max(permits_per_1000, na.rm = TRUE) - min(permits_per_1000, na.rm = TRUE)),
    rate_score = 100 * (permits_vs_growth - min(permits_vs_growth, na.rm = TRUE)) / 
                 (max(permits_vs_growth, na.rm = TRUE) - min(permits_vs_growth, na.rm = TRUE)),
    composite_score = (instant_score + rate_score) / 2
  )

6.1 Construction Hotspots: Where Building is Happening Now

Table: Construction Hotspots — Highest Current Production
Code
latest_year <- max(housing_growth_data$year, na.rm = TRUE)

instant_leaders <- housing_growth_data |>
  filter(year == latest_year) |>
  select(
    `Metro Area` = NAME,
    Year = year,
    Population = population,
    `New Permits` = new_housing_units_permitted,
    `Permits per 1000` = permits_per_1000,
    `Production Score` = instant_score
  ) |>
  mutate(
    `Permits per 1000` = round(`Permits per 1000`, 1),
    `Production Score` = round(`Production Score`, 1)
  ) |>
  arrange(desc(`Production Score`)) |>
  head(5)

datatable(
  instant_leaders,
  caption = paste("Construction Hotspots: Highest Current Housing Production -", latest_year),
  options = list(searching = FALSE)
)
Code
top_production <- instant_leaders$`Metro Area`[1]
top_production_score <- instant_leaders$`Production Score`[1]

Interpretation: Salisbury, MD Metro Area is currently the nation’s most active housing market, with a production score of 100.

This reflects strong near-term construction activity, signaling local policies that allow quick permitting and responsive homebuilding.

Such metros serve as models for short-run supply elasticity, showing that steady permitting can temper rent growth even in high-demand regions.

6.2 Growth-Responsive Housing Markets

Code
rate_leaders <- housing_growth_data |>
  filter(year == latest_year) |>
  select(
    `Metro Area` = NAME,
    Year = year,
    `5-Year Population Growth %` = pop_5yr_growth,
    `New Permits` = new_housing_units_permitted,
    `Growth Score` = rate_score
  ) |>
  mutate(
    `5-Year Population Growth %` = round(`5-Year Population Growth %`, 1),
    `Growth Score` = round(`Growth Score`, 1)
  ) |>
  arrange(desc(`Growth Score`)) |>
  head(5)

top_growth <- rate_leaders$`Metro Area`[1] 
top_growth_score <- rate_leaders$`Growth Score`[1]

Interpretation: Springfield, OH Metro Area demonstrates the most balanced housing response to population expansion, with a five-year growth-adjusted score of 7.7.

This means that new housing supply has kept pace with rapid population increases—an indicator of adaptive land-use policy and capacity planning that maintains affordability while accommodating in-migration.

Metros with low growth scores, by contrast, risk rising rent burdens as population outstrips new construction.

6.3 Overall Housing Growth

Code
composite_leaders <- housing_growth_data |>
  filter(year == latest_year) |>
  select(
    `Metro Area` = NAME,
    Year = year,
    `Production Score` = instant_score,
    `Growth Score` = rate_score,
    `Overall Score` = composite_score
  ) |>
  mutate(
    `Production Score` = round(`Production Score`, 1),
    `Growth Score` = round(`Growth Score`, 1),
    `Overall Score` = round(`Overall Score`, 1)
  ) |>
  arrange(desc(`Overall Score`)) |>
  head(5)

top_overall <- composite_leaders$`Metro Area`[1]
top_overall_score <- composite_leaders$`Overall Score`[1]

Interpretation: Punta Gorda, FL Metro Area leads the nation with an overall housing growth score of 28.6, balancing both strong construction volume and responsiveness to local population changes.

This composite result highlights how consistent permitting pipelines and pro-housing zoning frameworks can deliver stability across economic cycles.

Such metros illustrate the potential impact of federal-state collaboration on long-term housing affordability.

6.3.1 Policy Takeaway

Regions like Punta Gorda, FL Metro Area and Springfield, OH Metro Area show that consistent, multi-year housing production, most effectively keeps rent burdens stable.

Federal programs that reward steady permitting and year-over-year delivery can replicate this success across other metros.

7 Visualization

Code
# Join rent burden and housing growth datasets

yimby_base <- rent_burden_data |>
inner_join(housing_growth_data, by = c("City_Name" = "NAME", "year")) |>
select(City_Name, year, rent_burden_percent, burden_score,
population, pop_5yr_growth, composite_score)

# Calculate rent burden change, population growth, and housing growth
yimby_metrics <- yimby_base |>
group_by(City_Name) |>
mutate(
early_burden = mean(rent_burden_percent[year <= 2015], na.rm = TRUE),
recent_burden = mean(rent_burden_percent[year >= 2020], na.rm = TRUE),
burden_change = recent_burden - early_burden,
pop_growth = (max(population, na.rm = TRUE) - min(population, na.rm = TRUE)) /
min(population, na.rm = TRUE) * 100,
avg_housing_growth = mean(composite_score, na.rm = TRUE)
) |>
ungroup()

# Tag CBSAs based on the four rubric criteria

yimby_analysis <- yimby_metrics |>
mutate(
yimby_score = ifelse(
early_burden > median(early_burden, na.rm = TRUE) &
burden_change < 0 &
pop_growth > 0 &
avg_housing_growth > median(avg_housing_growth, na.rm = TRUE),
"YIMBY Success", "Other"
))

# Collapse to one row per CBSA for summary/plots

yimby_summary <- yimby_analysis |>
distinct(City_Name, .keep_all = TRUE)

# Four rubric criteria flags

yimby_flags <- yimby_summary |>
mutate(
high_early = early_burden > median(early_burden, na.rm = TRUE),
improved = burden_change < 0,
grew = pop_growth > 0,
above_avg_growth = avg_housing_growth > median(avg_housing_growth, na.rm = TRUE),
is_success_all4 = high_early & improved & grew & above_avg_growth
)

# Helpers for inline text
yimby_success_names <- yimby_flags |>
filter(is_success_all4) |>
arrange(burden_change) |>
pull(City_Name)

yimby_success_n <- length(yimby_success_names)
yimby_success_preview <- paste(head(yimby_success_names, 5), collapse = ", ")

7.1 Rent Burden vs Housing Growth

Code
library(ggplot2)

ggplot(yimby_summary,
aes(x = burden_change, y = avg_housing_growth, color = yimby_score)) +
geom_point(alpha = 0.6, size = 2) +
scale_color_manual(values = c("YIMBY Success" = "#2E8B57", "Other" = "gray70")) +
labs(
title = "Rent Burden Change vs Housing Growth",
subtitle = "Cities with strong housing growth tend to see rent burden improvements",
x = "Change in Rent Burden (percentage points)",
y = "Average Housing Growth Score",
color = "Metro Type"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold"),
plot.subtitle = element_text(size = 11, color = "gray40"),
legend.position = "bottom",
panel.grid.minor = element_blank()
)

Cities shown in green (“YIMBY Success”) built more housing and saw rent burdens stabilize or decline over time.

This pattern supports the idea that steady housing production helps prevent rent spikes, even in growing metros.

7.2 Population Growth vs Housing Affordability

Code
ggplot(yimby_summary,
aes(x = pop_growth, y = -burden_change, color = yimby_score)) +
geom_point(alpha = 0.6, size = 2) +
scale_color_manual(values = c("YIMBY Success" = "#457B9D", "Other" = "gray70")) +
labs(
title = "Population Growth vs Rent Burden Improvement",
subtitle = "Higher population growth with lower rent burden indicates strong housing supply response",
x = "Population Growth (%)",
y = "Rent Burden Improvement (percentage points)",
color = "Metro Type"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold"),
plot.subtitle = element_text(size = 11, color = "gray40"),
legend.position = "bottom",
panel.grid.minor = element_blank()
)

Many metros with strong population growth also achieved better affordability when new housing kept pace.

In contrast, regions with low construction saw rent burdens worsen — highlighting how growth without supply drives up costs.

7.3 Metros Achieving Affordability Through Construction

Table: Metropolitan Areas Improving Affordability Through Housing Supply (Top 10)
Code
yimby_success <- yimby_summary |>
  filter(yimby_score == "YIMBY Success") |>
  select(
    `Metro Area` = City_Name,
    `Early Rent Burden` = early_burden,
    `Rent Burden Change` = burden_change,
    `Population Growth %` = pop_growth,
    `Housing Growth Score` = avg_housing_growth
  ) |>
  mutate(
    `Early Rent Burden` = round(`Early Rent Burden`, 1),
    `Rent Burden Change` = round(`Rent Burden Change`, 1),
    `Population Growth %` = round(`Population Growth %`, 1),
    `Housing Growth Score` = round(`Housing Growth Score`, 1)
  ) |>
  arrange(desc(`Housing Growth Score`)) |>
  head(10)

DT::datatable(
  yimby_success,
  caption = "Metropolitan Areas Improving Affordability Through Housing Supply (Top 10)",
  options = list(pageLength = 10, searching = FALSE),
  rownames = FALSE
)

These metros represent the top 10 “YIMBY success stories” cities that started with relatively high rent burdens but achieved improvements over time while maintaining strong housing growth.

The leading metro, New Bern, NC Metro Area, saw a rent burden drop of 1.9 percentage points while maintaining a housing growth score of 34.9.

This demonstrates how steady new construction helps stabilize affordability even as populations rise.

Table: Recommended Congressional Sponsors
Code
# Primary sponsor: among YIMBY successes, pick the one with highest average housing growth
primary <- yimby_summary %>%
  filter(yimby_score == "YIMBY Success") %>%
  arrange(desc(avg_housing_growth)) %>%
  slice(1)

# Co-sponsor: highest recent burden among metros with below-median housing growth
hg_median <- median(yimby_summary$avg_housing_growth, na.rm = TRUE)
cosponsor <- yimby_summary %>%
  filter(avg_housing_growth <= hg_median) %>%
  arrange(desc(recent_burden)) %>%
  slice(1)

primary_name   <- primary$City_Name[1]
cosponsor_name <- cosponsor$City_Name[1]

sponsors <- tibble::tibble(
  Role = c("Primary Sponsor (YIMBY success)", "Co-Sponsor (High burden, low growth)"),
  `Metro Area` = c(primary_name, cosponsor_name),
  `Early Rent Burden %`  = c(round(primary$early_burden[1], 1),  round(cosponsor$early_burden[1], 1)),
  `Recent Rent Burden %` = c(round(primary$recent_burden[1], 1), round(cosponsor$recent_burden[1], 1)),
  `Change in Burden (pp)` = c(round(primary$burden_change[1], 1), round(cosponsor$burden_change[1], 1)),
  `Population Growth %`    = c(round(primary$pop_growth[1], 1),   round(cosponsor$pop_growth[1], 1)),
  `Avg Housing Growth Score` = c(round(primary$avg_housing_growth[1], 1), round(cosponsor$avg_housing_growth[1], 1))
)

DT::datatable(
  sponsors,
  caption = "Recommended Congressional Sponsors",
  options = list(pageLength = 5, searching = FALSE, lengthChange = FALSE),
  rownames = FALSE
)

The table highlights two contrasting metros that capture both success and need in housing reform.

  • The primary sponsor city, New Bern, NC Metro Area, achieved a rent burden decline of 1.9 percentage points and strong housing growth (34.9 score), proving that steady permitting can reduce affordability pressures.
  • The co-sponsor city, Miami-Fort Lauderdale-West Palm Beach, FL Metro Area, saw rent burden rise to 30.1% with limited housing growth (4.4 score), showing the cost of underbuilding.

Together, these cities make a compelling case for federal incentives that expand local housing capacity while maintaining affordability.

Code
# Map WAGES CBSA to names using POPULATION 
cbsa_map <- POPULATION %>%
  distinct(GEOID, NAME) %>%
  mutate(std_cbsa = paste0("C", GEOID)) %>%
  select(std_cbsa, NAME)

# Join wage data with metro names for readability
wages_named <- WAGES %>%
  mutate(std_cbsa = paste0(FIPS, "0")) %>%
  inner_join(cbsa_map, by = "std_cbsa")

# Filter for target metros and industries, then summarize
two_metros <- wages_named %>%
  filter(NAME %in% c(primary_name, cosponsor_name),
         INDUSTRY %in% c(23, 62)) %>%
  group_by(NAME, INDUSTRY) %>%
  summarise(
    Employment = sum(EMPLOYMENT, na.rm = TRUE),
    `Avg Annual Wage (USD)` = round(weighted.mean(AVG_WAGE, w = EMPLOYMENT, na.rm = TRUE), 0),
    .groups = "drop"
  ) %>%
  mutate(Industry = dplyr::case_when(
    INDUSTRY == 23 ~ "Construction (NAICS 23)",
    INDUSTRY == 62 ~ "Health Care & Social Assistance (NAICS 62)",
    TRUE ~ paste0("NAICS ", INDUSTRY)
  )) %>%
  select(Industry, Metro = NAME, Employment, `Avg Annual Wage (USD)`)

8 Policy Brief: A National Framework for Housing Affordability

MEMORANDUM

TO: Interested Members of Congress
FROM: Housing Policy Analyst
DATE: October 26, 2023
SUBJECT: The Need for Federal Incentives to Encourage Steady Local Housing Construction

1. Issue Overview

Rent burdens remain critically high across U.S. metropolitan areas, undermining household financial security and regional economic stability. This crisis persists even amid rising incomes and job growth, indicating a fundamental failure of housing supply to meet demand.

2. Key Findings

Data reveals a clear solution: metropolitan areas that maintain a consistent pipeline of new housing construction successfully lower rent burdens without negatively impacting population or job growth. The current challenge is that local permitting is often volatile, leading to short-term construction spikes rather than the steady, multi-year supply needed to stabilize markets.

3. Policy Recommendation

Congress should establish a federal incentive program that rewards local governments for sustaining higher rates of housing production. This program would use a composite metric to evaluate success, combining:

  • Current Construction Activity: Housing permits per 1,000 residents.

  • Responsive Growth: Whether permit issuance has kept pace with population growth over a five-year period.

4. Evidence for Action

The success of this approach is demonstrated by the contrasting outcomes in two metropolitan areas:

  • New Bern, NC Metro Area (Model for Success): By prioritizing consistent housing permits, this metro reduced its rent burden from 22.2% to 20.4% while its population grew 6.1%. This proves affordability is achievable alongside growth.

  • Miami-Fort Lauderdale-West Palm Beach, FL Metro Area (Case for Intervention): This city, where housing supply has lagged, saw its rent burden rise from 28.6% to 30.1% despite minimal population growth. It exemplifies the regions this bill is designed to help.

5. Coalition of Support

A federal incentive for housing production will build a powerful coalition, receiving strong support from major industries that benefit from stable housing markets:

  • Construction: Predictable permitting creates steady, skilled jobs. In New Bern, NC Metro Area, this sector employs over 1,595,772 workers with average wages of $54,289, while in Miami-Fort Lauderdale-West Palm Beach, FL Metro Area, it provides 14,900 jobs.

  • Health Care & Social Assistance: Affordable housing is key to retaining essential frontline staff. This sector employs 4,292,849 workers in New Bern, NC Metro Area and 53,721 in Miami-Fort Lauderdale-West Palm Beach, FL Metro Area—demonstrating its critical role in both regional and rural economies.

Conclusion

Housing affordability improves when cities build steadily, not sporadically.

This analysis shows that consistent permitting, supported by smart federal incentives, can help every metro area balance growth with livability.

By rewarding results and empowering local governments to build, this bill moves the nation from housing shortage to housing stability.


This work ©2025 was initially prepared as a Mini-Project for STA 9750 at Baruch College.
More details about the course can be found at the course site, and full assignment instructions are available under Mini-Project #02.